package br.com.pentagrama.service.impl;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;
import java.util.logging.Level;

import br.com.pentagrama.dto.NomeParametro;
import br.com.pentagrama.dto.Parametros;
import br.com.pentagrama.service.IDownloadUpload;
import br.com.pentagrama.service.ILog;
import br.com.pentagrama.util.ParseUtil;
import br.com.pentagrama.util.Sistema;
import br.com.pentagrama.util.TransferenciaUtil;

public class DownloadUpload implements IDownloadUpload {

	private Parametros parametros;
	
	private static DownloadUpload instance;
	
	private long tempo;
	
	private ILog log;
	
	private String link;
	
	private String host;
	
	private int porta;
	
	public static DownloadUpload getInstance(URL urlBase) {
		if(instance == null) {
			instance = new DownloadUpload(urlBase);
		}
		return instance;
	}
	
	private DownloadUpload(URL urlBase) {
		this.log = Sistema.getLog();
		this.link = urlBase.toString();
		this.host = urlBase.getHost();
		
		
		int portaUrl = urlBase.getPort();
		int portaDefault = urlBase.getDefaultPort();
		log.debug(Level.INFO, "Porta URL: " + portaUrl);
		log.debug(Level.INFO, "Porta DEFAULT: " + portaDefault);
		
		if(portaUrl > 0 ) {
			this.porta = portaUrl;
		} else {
			this.porta = portaDefault;
		}
		log.debug(Level.INFO, "Porta UTILIZADA: " + portaDefault);
		this.parametros = Sistema.getParametros();
		try {
			tempo = Long.parseLong(parametros.getChaveParametro().get(NomeParametro.TEMPO_TESTE));
		} catch (Exception e) {
			tempo = 30000;
		}
	}
	
	public byte[] accessLink(HttpURLConnection connection) {
		byte[] bytes = new byte[32];
		try {
		    connection.setDoInput(true);  
	        connection.setDoOutput(true);  
		    connection.connect();
		    InputStream is = connection.getInputStream();
		    bytes = TransferenciaUtil.convertStreamToBytes(is);
		} catch (Exception e) {
			e.printStackTrace();
			return new byte[0];
		}
	    return bytes;
	}
	
	public Double doDownload() {
		long totalDownload = 0;
		long delay = 1;
		try {
			String urlLinkRelativo = parametros.getChaveParametro().get(NomeParametro.PACOTE_GRANDE);
			String urlLink = link +  urlLinkRelativo;
			HttpURLConnection connection = null;
		    URL url = new URL(urlLink);
		    connection = (HttpURLConnection) url.openConnection();
		    connection.connect();
		    BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());
		    DownloadThread work = new DownloadThread(bis);
			
		    work.start();
		    long inicio = System.currentTimeMillis();
		    while(System.currentTimeMillis() < (inicio + tempo)) {
		    	Thread.sleep(100);
		    }
		    work.interrupt();
		    long fim = System.currentTimeMillis();
		    totalDownload = work.getTamanho();
		    delay = (fim - inicio) / 1000;
		    
		    log.info("Dados trafegados: " + totalDownload + " bytes");
		    log.info("Tempo do download: " + delay + " segundos");
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	    double bytesPorSegundo = totalDownload*(1.0)/(delay*1.0);
		return bytesPorSegundo*8; //multipica por 8 para retornar o numero de bits
	}

	public Double doUpload() {
		long totalUpload = 0;
		long delay = 1;
		try {
			log.debug(Level.INFO, "Upload");
			log.debug(Level.INFO, "Host: " + this.host);
			log.debug(Level.INFO, "Port: " + this.porta);
		    String ipPorta = this.host + ":" + this.porta ;
		    
		    String ip = ParseUtil.getIP(ipPorta);
			int porta = ParseUtil.getPorta(ipPorta);
			Socket s = new Socket(ip, porta);
			s.setReuseAddress(true);
			
		    UploadThread work = new UploadThread(s, ipPorta);
		    work.start();
		    long inicio = System.currentTimeMillis();
		    while(System.currentTimeMillis() < (inicio + tempo)) {
		    	Thread.sleep(100);
		    }
		    work.interrupt();
		    long fim = System.currentTimeMillis();
		    totalUpload = work.getTamanho();
		    delay = (fim - inicio) / 1000;
		    
		    log.info("Upload - Dados trafegados: " + totalUpload + " bytes");
		    log.info("Tempo do Upload: " + delay + " segundos");
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	    double bytesPorSegundo = totalUpload*(1.0)/(delay*1.0);
//	    log.info("Upload - Bytes por segundo: " + bytesPorSegundo);
		return bytesPorSegundo*8;
	}

}
